/*
 * @Date: 2024-11-25 13:31:38
 * @Author: LiSong
 * @LastEditors: LiSong
 * @LastEditTime: 2025-02-26 16:18:06
 * @Description: 
 */
import { v4 as uuidv4 } from 'uuid'

/**
 * 判断数据是否为空.
 *
 * For strings, it checks if the string is an empty string.
 * For arrays, it checks if the array has no elements.
 * For objects, it checks if the object has no own properties.
 * For other data types, it returns false.
 *
 * @param {any} value - The value to check.
 * @returns {boolean} - Returns true if the value is empty, false otherwise.
 */
export function isEmpty(value) {
  if (value === undefined || value === null) {
    return true;
  } else if (typeof value === 'string') {
    return value === '';
  } else if (Array.isArray(value)) {
    return value.length === 0;
  } else if (typeof value === 'object') {
    return Object.keys(value).length === 0;
  } else {
    return false;
  }
}
/**
 * 是否为JSON数据
 * 
 * @param {any} value 数据
 * @returns 
 */
export function isJSON(value) {
  try {
    if (isString(value)) {
      JSON.parse(value);
      return true;
    } else if (isObject(value)) {
      return true;
    } else {
      return false;
    }
  } catch (e) {
    return false;
  }
}
/**
 * 校验数据是否为Array
 *
 * @param {any} value - The value to check.
 * @returns {boolean} - Returns true if the value is an Array, false otherwise.
 */
export function isArray(value) {
  return Array.isArray(value);
}
/**
 * 是否为数字类型
 * 
 * @param {any} num 校验的内容
 * @returns 
 */
export function isNumber (num) {
  return typeof num === 'number' && !isNaN(num) && Infinity(num)
}
/**
 * 是否为字符串数据 
 *
 * @param {any} value 
 * @returns 
 */
export function isString(value) {
  return typeof value === 'string' || value instanceof String;
}
/**
 * 校验数据是否为Object
 *
 * @param {any} value The value to check.
 * @returns {boolean} Returns true if the value is an object, false otherwise.
 */
export function isObject(value) {
  return typeof value === 'object' && value !== null;
}
/**
 * Checks if the provided value is a function.
 *
 * Determines whether a given value is a function by checking its type
 * and constructor.
 *
 * @param {any} value - The value to check.
 * @returns {boolean} - Returns true if the value is a function, false otherwise.
 */
export function isFunction(value) {
  return value && (typeof value === 'function' || value instanceof Function || value.constructor === Function);
}

/**
 * 将字符串转换为 Base64 编码
 *
 * @param {string} value - The string to be converted.
 * @returns {string} - The Base64 encoded string.
 */
export function utf8ToBase64(value) {
  const bytes = new TextEncoder().encode(value);
  return btoa(String.fromCharCode(...bytes));
}

/**
 * 获取UUID
 * 
 * @param {Boolean} upperCase 是否大写
 * @returns {String} UUID
 */
export function getUUID (upperCase = false) {
  const uuid = uuidv4().replace(/-/g, '')
  return upperCase ? uuid.toUpperCase() : uuid
}
/**
 * 判断对象是否包含指定的KEY
 * 
 * @param {Object} obj 校验数据
 * @param {String} key 校验的KEY
 * @returns 
 */
export function hasOwnKey (obj, key) {
  if (isObject(obj) && !isArray(obj)) {
    return obj.hasOwnProperty(key)
  } else {
    return false
  }
}
/**
 * 深拷贝
 * 
 * @param {Object} obj 目标数据
 * @param {WeakMap} cache 是否缓存
 * @returns {Object} 返回数据
 */
export function deepClone (obj, cache = new WeakMap()) {
  if (typeof obj !== 'object' || obj === null) {
    return obj
  }
  if (cache.has(obj)) {
    return cache.get(obj)
  }

  if (Array.isArray(obj)) {
    const clonedArray = obj.map((item) => deepClone(item, cache));
    cache.set(obj, clonedArray);
    return clonedArray;
  }

  // 处理对象
  const clonedObj = {};
  cache.set(obj, clonedObj);
  Object.keys(obj).forEach((key) => {
    clonedObj[key] = deepClone(obj[key], cache);
  });
  return clonedObj;
}
/**
 * 获取目标对象指定路径下的值
 * 
 * @param {Object} obj 目标对象
 * @param {String} path 数据路径，格式为【xx.xx.xx】
 * @param {Object} defValue 默认数据
 * @returns {Object} 数据
 */
export function getValueByPath(obj, path, defValue) {
  // 将路径字符串拆分为数组
  const pathArray = path.split('.');
  // 逐步从对象中提取值
  let result = obj;
  for (let i = 0; i < pathArray.length; i++) {
    if (result == null) {
      // 如果中间的值为 null 或 undefined，返回默认值
      return defValue;
    }
    result = result[pathArray[i]];
  }
  // 如果最终的值为 undefined，返回默认值
  return result === undefined ? defValue : result;
}
/**
 * 设置目标对象指定路径下的值
 * 
 * @param {Object} obj 目标对象
 * @param {String} path 数据路径，格式为【xx.xx.xx】
 * @param {Object} value 设置的数据
 * @returns 设置后的数据
 */
export function setValueByPath(obj, path, value) {
  // 将路径字符串拆分为数组
  const pathArray = path.replace(/\[(\d+)\]/g, '.$1').split('.').filter(Boolean);

  // 逐步设置对象中的值
  let current = obj;

  for (let i = 0; i < pathArray.length - 1; i++) {
    const key = pathArray[i];
    // 如果当前对象的属性不存在，则创建一个新对象或数组
    if (current[key] == null) {
      // 如果路径部分是数字，创建数组；否则，创建对象
      current[key] = isNaN(Number(pathArray[i + 1])) ? {} : [];
    }
    
    current = current[key];
  }
  
  // 在路径的最后一层设置值
  current[pathArray[pathArray.length - 1]] = value;
  
  return obj;
}

function hexToRgb(hex) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}
function rgbToHex(r, g, b) {
  return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
export function lightenColor(color, amount) {
  const rgb = hexToRgb(color);
  const r = Math.min(255, rgb.r + amount);
  const g = Math.min(255, rgb.g + amount);
  const b = Math.min(255, rgb.b + amount);
  return rgbToHex(r, g, b);
}
